
package com.trydofor.id.exec;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;

import org.apache.mina.filter.firewall.Subnet;

import com.trydofor.aloe.exception.Exceptions;
import com.trydofor.id.doer.shell.ArgChecker;
import com.trydofor.id.doer.shell.Command;
import com.trydofor.id.doer.shell.Executer;
import com.trydofor.id.doer.shell.Outcome;
import com.trydofor.id.mina.WhitelistFilter;

/**
 * @author : Shi Rongjiu (www.trydofor.com)
 */
public class WhitelistExe implements Executer {
    
    private final Command         cmdAll;
    private final Command         cmdAdd;
    private final Command         cmdDel;
    private final WhitelistFilter whitelist;
    
    /**
     * constructor
     * 
     * @param whitelist the whitelist
     * @throws NullPointerException if whitelist is null
     */
    public WhitelistExe(WhitelistFilter whitelist) {
        Exceptions.checkNullPointer(whitelist);
        
        this.whitelist = whitelist;
        this.cmdAll = WhitelistCmd.listWhite();
        this.cmdAdd = WhitelistCmd.addWhite();
        this.cmdDel = WhitelistCmd.delWhite(whitelist);
    }
    
    /**
     * {@inheritDoc}
     */
    public Outcome execute(Command command, Map<String, String> argdata) {
        String err = ArgChecker.check(command, argdata);
        if (err != null) return new Outcome(-1, null, err);
        
        if (cmdAll.getAlias().equals(command.getAlias())) {
            return listWhiteList(command, argdata);
        }
        else if (cmdAdd.getAlias().equals(command.getAlias())) {
            return actWhiteList(command, argdata, true);
        }
        else if (cmdDel.getAlias().equals(command.getAlias())) {
            return actWhiteList(command, argdata, false);
        }
        return new Outcome(-1, null, "Command is unsupported:" + command);
    }
    
    // ------------------
    private Outcome listWhiteList(Command command, Map<String, String> argdata) {
        StringBuilder sb = new StringBuilder();
        for (Subnet net : whitelist.copyWhiteList()) {
            sb.append(net.toString());
            sb.append('\n');
        }
        return new Outcome(0, sb.toString(), null);
    }
    
    private Outcome actWhiteList(Command command, Map<String, String> argdata, boolean isAdd) {
        int status = 0;
        String output = null;
        String errput = null;
        String net = argdata.get("subnet");
        int pos = net.indexOf("/");
        try {
            Subnet subnet = null;
            if (pos < 0) {
                subnet = new Subnet(InetAddress.getByName(net), 32);
            }
            else {
                String ip = net.substring(0, pos);
                String mk = net.substring(pos + 1);
                subnet = new Subnet(InetAddress.getByName(ip), Integer.parseInt(mk));
            }
            
            if (isAdd) {
                whitelist.allow(subnet);
                output = "add the subnet=" + net + " to the white list";
            }
            else {
                whitelist.remove(subnet);
                output = "delete the subnet=" + net + " from the white list";
            }
        }
        catch (UnknownHostException e) {
            status = -1;
            errput = "unknown host,subnet=" + net;
        }
        
        return new Outcome(status, output, errput);
    }
}
